using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using NetProtocol.Enum;
using NetProtocol.POD;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// 关卡中的玩家数据
    /// </summary>
    public partial class LevelPlayer : BaseLevelFunctionHost
    {
        /// <summary>
        /// 这个就是LevelPlayerData的id
        /// </summary>
        public long id { get; private set; }
        /// <summary>
        /// 与视图层的会话
        /// </summary>
        public ISession session { get; set; }
        /// <summary>
        /// 关卡
        /// </summary>
        public Level level { get; set; }
        /// <summary>
        /// 地区
        /// </summary>
        public override LevelRegion region => _region;
        /// <summary>
        /// 玩家数据
        /// </summary>
        public LogicPlayer logicPlayer { get; set; }
        /// <summary>
        /// 队伍里所有的英雄
        /// </summary>
        public List<LevelHero> heroes { get; private set; }
        /// <summary>
        /// 队长英雄角色
        /// </summary>
        public LevelHero leaderHero { get; private set; }
        public LevelHeroEntity entity { get; private set; }
        /// <summary>
        /// 最靠近的存档点id
        /// </summary>
        public int checkPointId { get; private set; }
        /// <summary>
        /// 正在播放的对话总表id
        /// </summary>
        public int storyDialogCid { get; set; }

        public bool isReadyToStart { get; set; } = false;
        /// <summary>
        /// 正在跟随英雄的实体，该实体不会被占用英雄，需特殊纪录
        /// </summary>
        public LevelEntity entityFollowingMe { get; set; }
        /// <summary>
        /// 策划自定义相机
        /// </summary>
        public int customCameraCid { get; set; }
        /// <summary>
        /// 关卡发起的战斗id
        /// </summary>
        public long battleId { get; set; }
        /// <summary>
        /// 是否团灭
        /// </summary>
        public bool isTeamWipe { get; private set; }
        /// <summary>
        /// 是否操作权限正被系统接管
        /// </summary>
        public bool isTakenOverBySystem { get; internal set; }
        /// <summary>
        /// 快捷道具是否被禁用
        /// </summary>
        public bool isQuickBarDisabled { get; internal set; }
        /// <summary>
        /// 是否不可探测的，关卡中队伍/玩家化身如果进入死亡，待机等待动画等状态时，会处于不可探测的状态。
        /// 注意这里的不可探测通常是指不被怪物，机关等实体探测。
        /// </summary>
        public bool isUndetectable => isTeamWipe || isTakenOverBySystem || !isInMainPhasing;
        /// <summary>
        /// 是否处于无敌状态
        /// </summary>
        public bool isInvincible => _invincibleEndFrame >= level.levelFrame || !isInMainPhasing;
        /// <summary>
        /// 正在追踪中的实体(玩家手动追踪)
        /// </summary>
        public LevelEntity manualTrackingEntity { get; set; }
        /// <summary>
        /// 所属场景位面
        /// </summary>
        public GameScenePhasing gameScenePhasing { get; set; }
        public bool isInMainPhasing => gameScenePhasing == GameScenePhasing.Main;
        /// <summary>
        /// 正在跟踪的实体(不包括Area实体)
        /// 用于刷新aoi
        /// </summary>
        public HashSet<LevelEntity> trackQuestTargetsExceptArea = new HashSet<LevelEntity>();

        private List<LevelBuffPOD> _waitForInitBuffs;
        private LevelRegion _region;
        private int _invincibleEndFrame;

        public void InitId(long playerId, Level level)
        {
            id = playerId;
            this.level = level;
        }

        public void InitByPOD(LogicPlayer logicPlayer, LevelPlayerSavePOD playerSavePOD)
        {
            this.logicPlayer = logicPlayer;
            logicPlayer.levelPlayer = this;

            heroes = new List<LevelHero>();
            foreach (LogicHeroData heroData in logicPlayer.heroes.Values)
            {
                LevelHero hero = new LevelHero(this, heroData);
                heroes.Add(hero);
                if (leaderHero == null && hero.id == this.logicPlayer.leaderHeroId)
                {
                    leaderHero = hero;
                }
            }

            if (playerSavePOD != null)
            {
                checkPointId = playerSavePOD.checkPointId;
                _waitForInitBuffs = playerSavePOD.buffs.Count > 0 ? playerSavePOD.buffs : null;
                customCameraCid = playerSavePOD.customCameraCid;
                isQuickBarDisabled = playerSavePOD.isQuickBarDisabled;
            }
            else
            {
                checkPointId = 0;
                _waitForInitBuffs = null;
            }

            //hero entity
            LevelEntityPOD heroEntityPOD = playerSavePOD?.heroEntity;
            if (heroEntityPOD != null)
            {
                entity = LevelHeroEntity.CreateFromPool(heroEntityPOD);
            }
            else
            {
                entity = LevelHeroEntity.CreateFromPool(level.AllocateId());
            }
            entity.Init(this, leaderHero.heroData.skinCid);

            isReadyToStart = false;
        }

        /// <summary>
        /// 改变队长
        /// </summary>
        /// <param name="id">新队长id</param>
        /// <param name="isPassive">是否被动切换</param>
        public void ChangeLeaderHero(long id, bool isPassive = false)
        {
            foreach (var hero in heroes)
            {
                if (hero.heroData.id == id)
                {
                    ChangeLeaderHero(hero, isPassive);
                    break;
                }
            }
        }

        /// <summary>
        /// 改变队长
        /// </summary>
        /// <param name="hero">新队长</param>
        /// <param name="isPassive">是否被动切换</param>
        public void ChangeLeaderHero(LevelHero hero, bool isPassive = false)
        {
            leaderHero = hero;
            if (isPassive)
            {
                //按策划要求，被动切换队长时（如队长死亡），玩家需要有N秒的无敌时间，避免在切换时被继续伤害
                InvincibleForSec(LgLevelConst.PassiveChangeLeaderInvincibleSec);
            }
            region.NotifyLeaderHeroChanged(this);
        }

        public void AddHero(LogicHeroData heroData)
        {
            LevelHero hero = new LevelHero(this, heroData);
            heroes.Add(hero);
        }

        /// <summary>
        /// 查找英雄
        /// 同cid的英雄不能重复获得，因此根据cid查询，以后可考虑建额外缓存
        /// </summary>
        /// <param name="cid"></param>
        /// <returns></returns>
        public LevelHero GetHero(int cid)
        {
            foreach (LevelHero levelHero in heroes)
            {
                if (leaderHero.heroData.cid == cid)
                {
                    return leaderHero;
                }
            }
            return null;
        }

        public void SetEntity(LevelHeroEntity entity)
        {
            this.entity = entity;
        }

        /// <summary>
        /// 进入地区
        /// </summary>
        /// <param name="region"></param>
        public void OnEnterRegion(LevelRegion region)
        {
            this._region = region;
            entity.SetRegion(region);
            if (_waitForInitBuffs != null)
            {
                InitBuffs(_waitForInitBuffs);
                _waitForInitBuffs = null;
            }
            RefreshTrackQuestTargetEntity();
            //应策划要求，传送后要清除手动跟踪的实体
            manualTrackingEntity = null;
            gameScenePhasing = GameScenePhasing.Main;
        }

        /// <summary>
        /// 帧刷
        /// </summary>
        public void LogicOnUpdate()
        {
            if (entity != null)
            {
                entity.LogicOnUpdate();
            }
            _buffManager?.LogicOnUpdate();
        }

        public bool ClientMoveHero(Vector3Logic position)
        {
            return entity.ClientMove(position);
        }

        public void OnLeaveLevel()
        {
            SaveCheckPoint();
            if (_buffManager != null)
            {
                _buffManager.RemoveAll();
            }
            entity.ClearOccupation(true);
        }

        public void SaveCheckPoint()
        {
            LevelEntity nearestCheckPoint = null;
            List<LevelEntity> checkPoints = ListPool<LevelEntity>.Get();
            {
                region.GetEntitiesByTagOrMcid((int)LevelEntityTag.CheckPoint, checkPoints);
                float minDis = float.MaxValue;
                for (int i = 0; i < checkPoints.Count; i++)
                {
                    LevelEntity checkPoint = checkPoints[i];
                    if (checkPoint.isCheckPointActive)
                    {
                        Vector3Logic heroToCheckPoint = checkPoint.position - entity.position;
                        if (heroToCheckPoint.sqrMagnitude < minDis)
                        {
                            minDis = heroToCheckPoint.sqrMagnitude;
                            nearestCheckPoint = checkPoint;
                        }
                    }
                }
                ListPool<LevelEntity>.Put(checkPoints);
            }
            if (nearestCheckPoint != null)
            {
                checkPointId = nearestCheckPoint.id;
            }
            else
            {
                checkPointId = 0;
            }
        }

        /// <summary>
        /// AOI接口
        /// 是否属于aoi列表范围内的实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns>是否是aoi实体</returns>
        public bool IsInterested(LevelEntity entity, bool includeInactive = false, bool includeRemoved = false)
        {
            if (entity == null)
                return false;
            if ((includeInactive || entity.isActive) || (includeRemoved || !entity.isRemoved))
            {
                if (entity.HasDynamicParam(EntityDynamicParamType.Area))
                {
                    return true;
                }
                return this.entity.aoiEntities.Contains(entity);
            }
            return false;
        }

        /// <summary>
        /// AOI接口
        /// 获取属于aoi列表范围内的实体
        /// </summary>
        /// <param name="entities">需要被检查的实体</param>
        /// <param name="interestedEntities">所有aoi列表内的实体的容器，方法调用完毕后，该列表即所有实体的列表，所以需确保传入时是空的</param>
        /// <returns>是否包含aoi实体</returns>
        public bool GetInterestedFromList(IReadOnlyList<LevelEntity> entities, List<LevelEntity> interestedEntities, bool includeInactive = false, bool includeRemoved = false)
        {
            for (int i = 0; i < entities.Count; i++)
            {
                LevelEntity entity = entities[i];
                if (IsInterested(entity, includeInactive, includeRemoved))
                {
                    interestedEntities.Add(entity);
                }
            }
            return interestedEntities.Count > 0;
        }

        public override bool TriggerBuffService(ServiceTriggerType triggerType)
        {
            bool hasSuccess = base.TriggerBuffService(triggerType);
            for (int i = 0; i < heroes.Count; i++)
            {
                bool hasSuc = heroes[i].TriggerBuffService(triggerType);
                if (hasSuc)
                {
                    hasSuccess = true;
                }
            }
            return hasSuccess;
        }

        /// <summary>
        /// 刷新当前追踪的任务目标实体
        /// 不包括区域实体
        /// 用于刷新aoi
        /// </summary>
        public void RefreshTrackQuestTargetEntity()
        {
            int questCid = logicPlayer.trackQuestCid;
            if (questCid == 0)
            {
                trackQuestTargetsExceptArea.Clear();
                return;
            }
            var cfgQuest = TableCenter.quest.Get(questCid);
            if (cfgQuest.TargetRegion != region.CfgRegionInstance.Id)
            {
                trackQuestTargetsExceptArea.Clear();
                return;
            }
            foreach (var mcid in cfgQuest.TargetShowEntity)
            {
                var entity = region.GetEntityByMcid(mcid);
                //区域实体仅进入地区时通知添加，不进入aoi列表，也不会因为AOI变化移除
                //如果追踪的是区域实体，则一定在AOI中无需考虑
                if (entity.HasDynamicParam(EntityDynamicParamType.Area))
                {
                    continue;
                }
                trackQuestTargetsExceptArea.Add(entity);
            }
        }

        /// <summary>
        /// 检查团队血量，队长是否死亡，是否团灭
        /// </summary>
        /// <returns></returns>
        public void CheckTeamHP()
        {
            if (isTeamWipe)
            {
                return;
            }
            isTeamWipe = true;
            var oldLeader = leaderHero;
            bool isLeaderDead = leaderHero.isDead;
            foreach (var hero in heroes)
            {
                if (!hero.isDead)
                {
                    isTeamWipe = false;
                    //如果队长死了，且不是团灭，则替换队长
                    if (isLeaderDead)
                    {
                        ChangeLeaderHero(hero, true);
                    }
                    break;
                }
            }
            //队长死亡清队长buff
            if (!isTeamWipe && isLeaderDead)
            {
                oldLeader.buffManager.Clear();
                region.NotifyClearHeroBuff(this, oldLeader.id);
            }
            //团灭等待玩家选择是否复活，复活后再处理清buff回血等逻辑
            else if (isTeamWipe)
            {
                region.NotifyTeamWipe(this);
            }
        }

        /// <summary>
        /// 无敌N秒
        /// </summary>
        /// <param name="second">指定无敌时间（秒）</param>
        private void InvincibleForSec(float second)
        {
            _invincibleEndFrame = level.levelFrame + (int)(second * LgLevelConst.FrameRate);
        }

        /// <summary>
        /// 响应客户端请求并复活
        /// </summary>
        public void Revive()
        {
            //清buff，回血
            foreach (var hero in heroes)
            {
                hero.buffManager?.Clear();
                hero.ResetLevelAttr();
            }
            isTeamWipe = false;
            buffManager?.Clear();
            //同步英雄血量

            //传送到最近的存档点
            var entity = region.GetNearestPortal(this);
            if (entity == null)
            {
                LogicLog.LogError("复活传送失败，找不到任何存档点，也找不到出生点");
                return;
            }
            region.TeleportAndNotify(this, entity.position);
            region.NotifyHeroesAttr(this, heroes, NetProtocol.Enum.AttrChangeReason.Revive);
            region.NotifyRevive(this);
        }

        /// <summary>
        /// 是否是正在追踪的实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool isTrackingEntity(LevelEntity entity)
        {
            if (entity == null)
            {
                return false;
            }
            return trackQuestTargetsExceptArea.Contains(entity) || manualTrackingEntity == entity;
        }

        /// <summary>
        /// 创建发送给视图层的数据
        /// </summary>
        /// <returns></returns>
        public override IPOD GeneratePOD()
        {
            LevelPlayerPOD pod = new LevelPlayerPOD();
            pod.id = logicPlayer.id;
            pod.name = logicPlayer.name;
            pod.level = logicPlayer.level;
            pod.exp = logicPlayer.exp;
            pod.avatar = logicPlayer.avatar;
            pod.avatarFrame = logicPlayer.avatarFrame;

            pod.unsafe_heroes = heroes?.ConvertAll((hero) => hero.GeneratePOD() as LevelHeroPOD);
            pod.leaderHeroId = logicPlayer.leaderHeroId;
            pod.unsafe_buffs = buffManager?.GenerateBuffPODs();
            pod.followerId = entityFollowingMe == null ? 0 : entityFollowingMe.id;
            pod.customCameraCid = customCameraCid;
            pod.isQuickBarDisabled = isQuickBarDisabled;
            return pod;
        }

        public LevelOtherPlayerPOD GenOtherPlayerPOD()
        {
            LevelOtherPlayerPOD pod = new LevelOtherPlayerPOD();
            pod.id = logicPlayer.id;
            pod.name = logicPlayer.name;
            pod.level = logicPlayer.level;
            pod.exp = logicPlayer.exp;
            pod.avatar = logicPlayer.avatar;
            pod.avatarFrame = logicPlayer.avatarFrame;
            pod.unsafe_heroes = heroes?.ConvertAll((hero) => hero.GeneratePOD() as LevelHeroPOD);
            pod.leaderHeroId = logicPlayer.leaderHeroId;
            return pod;
        }

        public LevelPlayerSavePOD GenerateSavePOD()
        {
            LevelPlayerSavePOD pod = new LevelPlayerSavePOD();
            pod.checkPointId = checkPointId;
            pod.unsafe_buffs = _buffManager?.GenerateBuffPODs();
            pod.followEntityId = entityFollowingMe == null ? 0 : entityFollowingMe.id;
            pod.customCameraCid = customCameraCid;
            pod.heroEntity = entity.GeneratePOD() as LevelEntityPOD;
            pod.isQuickBarDisabled = isQuickBarDisabled;
            return pod;
        }

        public override void OnReset()
        {
            base.OnReset();
            id = 0;
            session = null;
            if (logicPlayer != null)
            {
                logicPlayer.levelPlayer = null;
            }
            logicPlayer = null;
            level = null;
            foreach (var hero in heroes)
            {
                hero.OnReset();
            }
            heroes.Clear();
            heroes = null;
            leaderHero = null;
            ClassPool.Put(entity);
            entity = null;
            checkPointId = 0;
            _waitForInitBuffs = null;
            storyDialogCid = 0;
            isReadyToStart = false;
            entityFollowingMe = null;
            _region = null;
        }
    }

}
